/*
 * Copyright (c) 2009, dana koch
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */
package btplay;

import java.io.*;
import java.util.*;

import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import net.rim.device.api.media.control.AudioPathControl;

import javax.microedition.media.control.VolumeControl;
import javax.microedition.media.Control;
import javax.microedition.media.Manager;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.io.*;
import javax.microedition.io.file.*;

final class PlayScreen extends MainScreen 
{
   PlayerController player;
   
   TimeUpdateTask task;
   ButtonField play;
   LabelField file;
   LabelField time;
   
   PlayScreen()
   {
      this.player = new PlayerController();
      construct();
   }
   
   private void construct()
   {
      VerticalFieldManager v;
      HorizontalFieldManager row, row2;
      ButtonField open, reverse, reverse2, forward2, forward;
      
      setTitle("btplay");
      
      v = new VerticalFieldManager();
      
      // First row 
      row = new HorizontalFieldManager();
      open = new ButtonField("Open", ButtonField.CONSUME_CLICK);
      file = new LabelField("");
      row.add(open);
      row.add(file);
      v.add(row);
      
      // Second row 
      row2 = new HorizontalFieldManager();
      play = new ButtonField("Play", ButtonField.CONSUME_CLICK);
      reverse = new ButtonField("< ", ButtonField.CONSUME_CLICK);
      reverse2 = new ButtonField("<<", ButtonField.CONSUME_CLICK);
      forward2 = new ButtonField(">>", ButtonField.CONSUME_CLICK);
      forward = new ButtonField(" >", ButtonField.CONSUME_CLICK);
      row2.add(play);
      row2.add(reverse);
      row2.add(reverse2);
      row2.add(forward2);
      row2.add(forward);
      v.add(row2);
      
      time = new LabelField("");
      v.add(time);
      
      play(play);
      time(time);
      file(file);
      
      open.setChangeListener(new OpenButtonListener(this));
      play.setChangeListener(new PlayButtonListener(this));
      
      reverse.setChangeListener(new SkipButtonListener(this, 5, false));
      reverse2.setChangeListener(new SkipButtonListener(this, 15, false));
      forward2.setChangeListener(new SkipButtonListener(this, 15, true));
      forward.setChangeListener(new SkipButtonListener(this, 5, true));
      
      add(v);
   }
   
   public void play(ButtonField play) 
   { 
      this.play = play; 
   }
   
   public ButtonField play() 
   { 
      return this.play; 
   }
   
   public void task(TimeUpdateTask task) 
   { 
      this.task = task; 
   }   
   
   public TimeUpdateTask task() 
   { 
      return this.task; 
   }
   
   public void file(LabelField file) 
   {
      this.file = file; 
   }
   
   public LabelField file() 
   { 
      return this.file; 
   }
   
   public void time(LabelField time)
   { 
      this.time = time; 
   }
  
   public LabelField time() 
   { 
      return this.time; 
   }
    
   public boolean onSavePrompt() 
   { 
      return true; 
   }
   
   public void choose()
   {
      FileChooserController chooser = new FileChooserController();
      String path = chooser.getPath();
      
      
      file().setText(path);
      
      if(player.inited())
         stop();
   }
   
   public void stop()
   {
      try
      {
         if(player != null)
         {
            player.close();
         }
         task().update(false);
         play().setLabel("Play");
         time().setText("");
      }
      catch(Exception e)
      {
         PlayerController.alert("stop: " + e.toString());
      }
   }
   
   public void playpause()
   {
      if(!player.inited())
      {
         String filename;
         task(new TimeUpdateTask(player, this));
          
         filename = file.getText();
         if(!filename.equals(""))
            player.init(file().getText(), new PlayerControllerListener(this));
         else
            return;
      }
       
      int id;

      if(play().getLabel().equals("Play"))
      {
         player.ready();

         task().update(true);
         id = UiApplication.getApplication().invokeLater(task(), 500, true);

         player.play();
         play().setLabel("Pause");
      } 
      else // if(play.getLabel().equals("Pause")
      {
         player.pause();

         task().update(false);
         play().setLabel("Play");
      }
   }
   
   public void skip(boolean forward, int seconds)
   {
      if(!player.inited())
         return;
         
      if(forward)
         player.skipForward(seconds);
      else
         player.skipBackward(seconds);
   }
   
   public void reset()
   {
      task().update(false);
      play().setLabel("Play");
   }
} 

final class OpenButtonListener implements FieldChangeListener
{
   private PlayScreen screen;
   
   OpenButtonListener(PlayScreen screen)
   {
      this.screen = screen;
   }
   
   public void fieldChanged(Field field, int context) 
   {
      screen.choose();
   }
}

final class PlayButtonListener implements FieldChangeListener
{
   private PlayScreen screen;
    
   PlayButtonListener(PlayScreen screen)
   {
      this.screen = screen;
   }
    
   public void fieldChanged(Field field, int context) 
   {  
      screen.playpause();
   }
}

final class SkipButtonListener implements FieldChangeListener
{
    private PlayScreen screen;
    private int seconds = 0;
    private boolean forward;
    
    SkipButtonListener(PlayScreen screen, int seconds, 
       boolean forward)
    {
       this.screen = screen;
       this.seconds = seconds;
       this.forward = forward;
    }
    
    public void fieldChanged(Field field, int context) 
    {
       screen.skip(forward, seconds);
    }  
}

final class PlayerControllerListener implements PlayerListener
{
   PlayScreen screen;
   
   PlayerControllerListener(PlayScreen screen)
   {
      this.screen = screen;
   }
   
   public void playerUpdate(Player player, String event, Object eventData)
   {
      if(event == PlayerListener.END_OF_MEDIA) 
      {
         screen.reset();
         return;
      }
   }
} 

final class TimeUpdateTask implements Runnable
{
   private boolean update;
   private PlayScreen screen;
   private PlayerController player; 
   
   TimeUpdateTask(PlayerController player, PlayScreen screen)
   {
      this.screen = screen;
      this.player = player;
   }
   
   public void update(boolean update)
   {
      this.update = update;
   }
   
   public void run()
   {
      if(update == false)
         return;
         
      long time_microseconds = 0;
      
      try 
      {
         time_microseconds = player.getMediaTime();
      }
      catch(Exception e) { }
      
      int time_seconds = (int) Math.floor((float)time_microseconds / (float)1000000 + 0.5);
      
      int hours = time_seconds / (60 * 60);
      int minutes = (time_seconds - hours * 60 * 60) / 60;
      int seconds = time_seconds - hours * 60 * 60 - minutes * 60;
      
      String time_string = PlayerController.formatTime(hours, minutes, seconds);
      String duration_string = player.duration();
      
      synchronized(UiApplication.getApplication().getEventLock())
      {
         screen.time().setText(time_string + " / " + duration_string);
      }
   }
}


